package com.itheima.demo;

import com.alibaba.fastjson.JSON;
import com.itheima.pojo.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * 文档搜索
 * @作者 itcast
 * @创建日期 2020/11/7 8:54
 **/
public class EsDemo05 {
    RestHighLevelClient client;


    @Test
    public void aggregations() throws IOException {
        //1. 创建搜索请求
        SearchRequest searchRequest = new SearchRequest("user");
        //  封装查询条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 通过工具类 AggregationBuilders 可以快捷的构建 聚合条件
        // 方法名: 聚合类型   参数1: 自定义的聚合名称
        TermsAggregationBuilder termsBuilder = AggregationBuilders.terms("terms_by_gender").field("gender");
        AvgAggregationBuilder avgBuilder = AggregationBuilders.avg("avg_by_age").field("age");
        // 分桶之后再求平均值
        termsBuilder.subAggregation(avgBuilder);
        builder.aggregation(termsBuilder);
        // 设置搜索条件内容
        searchRequest.source(builder);
        //2. 执行搜索
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        // 获取聚合结果  总的聚合结果
        Aggregations aggregations = searchResponse.getAggregations();
        // 根据自定义的聚合名称 找到对应的聚合类型处理结果
        // 注意: 你是什么聚合类型，用对应的聚合类型接口来接收
        Terms termsResult = aggregations.get("terms_by_gender");
        // 处理的分桶信息
        List<? extends Terms.Bucket> buckets = termsResult.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            System.out.println("当前分桶的key==> " + bucket.getKeyAsString());
            System.out.println("当前分桶的文档数量==> " + bucket.getDocCount());
            // 获取 子聚合的总结果
            Aggregations subAggs = bucket.getAggregations();
            // 在子聚合结果中 找到对应自定名称的聚合处理结果
            Avg avgResult = subAggs.get("avg_by_age");
            System.out.println("当前分桶的平均值==>"+avgResult.getValue());
        }
    }
    /**
     * match:   note  唱歌javaee
     * note:  如果匹配到了对应关键词 能有一个高亮的显示
     */
    @Test
    public void highlight() throws IOException {
        //1. 创建搜索请求
        SearchRequest searchRequest = new SearchRequest("user");
        //  封装查询条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        //  分词查询条件 note: 唱歌javaee
        builder.query(QueryBuilders.matchQuery("note","唱歌javaee"));
        //  构建高亮的条件
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //  高亮字段
        highlightBuilder.field("note");
        // 前置标签
        highlightBuilder.preTags("<span>");
        // 后置标签
        highlightBuilder.postTags("</span>");
        builder.highlighter(highlightBuilder);
        // 设置搜索条件内容
        searchRequest.source(builder);
        //2. 执行搜索
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        System.out.println("查询到的总结果数量==>" + hits.getTotalHits().value);
        SearchHit[] docList = hits.getHits();
        for (SearchHit searchHit : docList) {
            String userJson = searchHit.getSourceAsString();
            User user = JSON.parseObject(userJson, User.class);
            // 处理高亮结果
            Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
            // 得到 note字段的高亮处理结果
            HighlightField noteHighlightResult = highlightFields.get("note");
            // 获取所有的高亮片段， 结果是一个数组
            Text[] fragments = noteHighlightResult.getFragments();
            // 将所有片段拼接成一个字段得到高亮字段结果
//            StringUtils.join(fragments);
             // final   final char[]
            StringBuilder sb = new StringBuilder();
            for (Text fragment : fragments) {
                sb.append(fragment);
            }
            // 将高亮结果，替换user对象中的note字段内容
            user.setNote(sb.toString());


            System.out.println(user);
        }
    }

    /**
     * 搜索全部
     */
    @Test
    public void matchAll() throws IOException {
//        1. 创建搜索请求对象  (SearchRequest )
        SearchRequest searchRequest = new SearchRequest("user");
//        所有的请求参数 通过 SearchSourceBuilder 统一构建
        SearchSourceBuilder builder = new SearchSourceBuilder();
// 		.query方法 设置查询条件
        builder.query(QueryBuilders.matchAllQuery());
//        提供工具类创建对应条件类型
//                QueryBuilders
// 		.sort方法 设置排序条件
// 		.from
//                .size   设置分页条件
// 		.highlight 设置高亮条件1
// 		.aggregations 设置聚合条件
//        将builder对象设置到搜索请求的source方法中
        searchRequest.source(builder);
//        2. 客户端执行 .search搜索方法
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
//        3. 解析结果 (SearchResponse)
        //searchResponse
//                .getHits 得到查询结果
        SearchHits hits = searchResponse.getHits();
//                .getTotalHits
        System.out.println("查询结果数量==>" + hits.getTotalHits().value);
//                .value 得到查询的结果数量
// 			.getHits
        SearchHit[] docList = hits.getHits();
//                遍历文档列表数组
        for (SearchHit searchHit : docList) {
            String userJson = searchHit.getSourceAsString();
            User user = JSON.parseObject(userJson, User.class);
            System.out.println(user);
        }
// 					.getSource
//                .getHighlight
//                .getAggregations 得到的是聚合总结果
    }



    /**
     * 初始化es的客户端
     */
    @Before
    public void init(){
         client = new RestHighLevelClient(
                RestClient.builder(new HttpHost("localhost",9200))
        );
    }

    /**
     * 关闭客户端
     */
    @After
    public void close(){
        try {
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
